﻿/*
 *  Copyright (C) 2019  刘臣轩
                  2021  贺龙宇
                  2022  贺龙宇 张伊男
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once

#include "../SerialPort/Protocol.h"
#include "../Config/FightingParam.h"
#include "opencv2/opencv.hpp"
#include <opencv2/ml/ml.hpp>
#include "../define.h"
#include "../Log/log.h"



enum class ArmorType : uchar { BIG, SMALL}; /*大小装甲板*/
class ArmorDetector {
public:
    ArmorDetector();
    ~ArmorDetector();
    bool DetectArmor(cv::Mat& src, std::vector<cv::Rect> &box, std::vector<int> &id);/*外部调用函数*/
  

public:
	friend class SolvePos;

private://variable
    /*debug用*/
    cv::Mat show_lights; /*灯条帧*/
    cv::Mat show_armors; /*装甲板帧*/
    cv::Mat show_final_armor; /*最终结果帧*/
    cv::Mat show_rect;
    const std::vector<cv::Point2f> armor_points 
    { cv::Point2f(0, 0), cv::Point2f(armorParam.small_armor_width, 0),
      cv::Point2f(armorParam.small_armor_width, armorParam.armor_height),
      cv::Point2f(0, armorParam.armor_height) };
    std::vector<cv::Mat> number_template;/*数字模板。在每次程序启动时会把模板读入*/
    /* 基地8(level_5) > 哨兵7(level_4) > 英雄1(level_3) > 步兵345(level_2) > 工程2(level_1) > 无0(level_0)) */
    const int number_level[9] = { 0, 3, 1, 2, 2, 2, 3, 4, 5 }; /*装甲板权重，目前该模块已移植到SolvePos模块中*/


    cv::Ptr<cv::ml::KNearest> knn;



private://functions

    cv::Mat DistillationColor(const cv::Mat& src);/*颜色过滤，提取红色通道或蓝色通道*/
    inline void DrawRotatedRect(const cv::Mat& image, const cv::RotatedRect& rect, const cv::Scalar& color, int thickness);/*画旋转矩形*/
    void DetectLights(const cv::Mat& src, std::vector<cv::RotatedRect>& lights);/*灯条检测*/
    inline void DrawArmor(const cv::Mat& image, const std::vector<cv::Point2f>& armor, const cv::Scalar& color, int thickness);/*绘制装甲板*/
    void PossibleArmors(const std::vector<cv::RotatedRect>& lights, std::vector<std::vector<cv::Point2f>>& armors);/*拟合可能的装甲板*/
    void CalcArmorInfo(std::vector<cv::Point2f>& armor, const cv::RotatedRect& left_light, const cv::RotatedRect& right_light);/*计算装甲板的信息*/
    ArmorType DetectArmorType(std::vector<cv::Point2f> &armor); /*判断装甲板大小*/
    int DetectNumber(const cv::Mat& perspective,const ArmorType &armor_type);/*数字检测*/
    void GetArmorNumber(const cv::Mat& src, std::vector<std::vector<cv::Point2f>>& armors, std::vector<int>& id);/*获取所有识别到的装甲板的数字*/
    void CalcControlInfo(const std::vector<cv::Point2f>& armor, cv::Point3f& target);/*位置解算，目前已移植至SolvePos模块中*/
    // void CalsolvePnP(const std::vector<cv::Point2f>& armor, cv::Point3f& target);/*SolvePnP测算距离，已弃用*/
    // void KalmanPredict(const std::vector<cv::Point2f>& armor, cv::Point3f& target);/*卡尔曼滤波预测，已弃用*/
    void GetPrimaryThreshold(const cv::Mat& src);/*获取进行颜色和亮度二值化的阈值*/
    bool GetNumberThreshold(const cv::Mat &src, const std::vector<cv::Point2f> &armor);/*获取进行数字二值化的阈值*/
    void SerialChecking();//用于检查串口状态

};


